package cn.stylefeng.guns.modular.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.exception.BusinessException;
import cn.stylefeng.guns.modular.business.constans.DeviceTypeEnum;
import cn.stylefeng.guns.modular.business.dto.DeviceAddDto;
import cn.stylefeng.guns.modular.business.dto.DeviceQuery;
import cn.stylefeng.guns.modular.business.dto.DeviceUpdateDto;
import cn.stylefeng.guns.modular.business.entity.Device;
import cn.stylefeng.guns.modular.business.entity.DeviceBrand;
import cn.stylefeng.guns.modular.business.exception.DeviceBrandExceptionEnum;
import cn.stylefeng.guns.modular.business.exception.DeviceExceptionEnum;
import cn.stylefeng.guns.modular.business.mapper.DeviceBrandMapper;
import cn.stylefeng.guns.modular.business.mapper.DeviceMapper;
import cn.stylefeng.guns.modular.business.service.DeviceService;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.dict.modular.mapper.DictMapper;
import cn.stylefeng.roses.kernel.dsctn.api.annotation.DataSource;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private DeviceBrandMapper deviceBrandMapper;

    @Autowired
    private DictMapper dictMapper;

    @Override
    @DataSource(name = "business")
    public PageResult<Device> findPage(DeviceQuery deviceDto) {
        Page<Device>  page = new Page<>(deviceDto.getPageNo(),deviceDto.getPageSize());
        QueryWrapper<Device> qw = new QueryWrapper<>();
        if (StringUtils.isNotBlank(deviceDto.getDeviceSn())) {
            deviceDto.setDeviceSn(deviceDto.getDeviceSn().toLowerCase().trim());
        }
        qw.like(StringUtils.isNotBlank(deviceDto.getDeviceSn()), Device.COL_DEVICE_SN,deviceDto.getDeviceSn());
        qw.eq(deviceDto.getDeviceType()!=null, Device.COL_DEVICE_TYPE,deviceDto.getDeviceType());
        qw.orderByDesc(Device.COL_ID);
        this.deviceMapper.selectPage(page,qw);
        return PageResultFactory.createPageResult(page);
    }

    @Override
    @DataSource(name = "business")
    public Device detail(Integer id) {
        Device device = this.deviceMapper.selectById(id);
        if(ObjectUtil.isEmpty(device)) {
            throw new BusinessException(DeviceExceptionEnum.DEVICE_NOT_EXISTED);
        }
        return device;
    }

    @Override
    @DataSource(name = "business")
    public void edit(DeviceUpdateDto deviceUpdateDto) {
        QueryWrapper<DeviceBrand> qwBrand = new QueryWrapper<>();
        qwBrand.eq(DeviceBrand.COL_DEVCIE_BRAND_ID,deviceUpdateDto.getDeviceBrandId());
        DeviceBrand deviceBrand = this.deviceBrandMapper.selectOne(qwBrand);
        if(ObjectUtil.isEmpty(deviceBrand)) {
            throw new BusinessException(DeviceBrandExceptionEnum.DEVICEBRAND_NOT_EXISTED);
        }
        Device device = this.deviceMapper.selectById(deviceUpdateDto.getId());
        if(ObjectUtil.isEmpty(device)) {
            throw new BusinessException(DeviceExceptionEnum.DEVICE_NOT_EXISTED);
        }
        BeanUtil.copyProperties(deviceUpdateDto, device,"createTime","deviceLastTime");
//        Long time  = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(deviceUpdateDto.getLastTime(), new ParsePosition(0)).getTime() / 1000;
        device.setDeviceBrand(deviceBrand.getName());
        device.setLastTime(DateUtil.date());
        device.setDeviceLastTime((int)deviceUpdateDto.getDeviceLastTime().getTime());
        this.deviceMapper.updateById(device);
    }

    @Override
    @DataSource(name = "business")
    public void add(DeviceAddDto deviceAddDto) {

        QueryWrapper<DeviceBrand> qwBrand = new QueryWrapper<>();
        qwBrand.eq(DeviceBrand.COL_DEVCIE_BRAND_ID,deviceAddDto.getDeviceBrandId());
        DeviceBrand deviceBrand = this.deviceBrandMapper.selectOne(qwBrand);
        if(ObjectUtil.isEmpty(deviceBrand)) {
            throw new BusinessException(DeviceBrandExceptionEnum.DEVICEBRAND_NOT_EXISTED);
        }
        Device device = new Device();
        BeanUtil.copyProperties(deviceAddDto,device);
        device.setDeviceLastTime(0);
        device.setLastTime(DateUtil.date());
        long time = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        device.setCreateTime((int)(time / 1000));
        device.setDeviceBrand(deviceBrand.getName());
        this.deviceMapper.insert(device);
    }

    @Override
    @DataSource(name = "business")
    public Map<String, Object> statistics() {
        Map<String, Object> map = new HashMap<>();
        Integer towenCount = 0;
        Integer liftCount = 0;
        Integer hookCount = 0;
        Integer alCount = 0;
        Integer monitorCount = 0;
        Integer eleCount = 0;
        List<Device> devices = this.deviceMapper.selectList(new QueryWrapper<Device>());
        for(Device device : devices) {
            if(device.getDeviceType() == DeviceTypeEnum.TOWEN.getIndex()) {
                towenCount++;
            }else if(device.getDeviceType() == DeviceTypeEnum.LIFT.getIndex()) {
                liftCount++;
            }else if(device.getDeviceType() == DeviceTypeEnum.HOOK.getIndex()) {
                hookCount++;
            }else if(device.getDeviceType() == DeviceTypeEnum.AL.getIndex()) {
                alCount++;
            }else if(device.getDeviceType() == DeviceTypeEnum.MONITOR.getIndex()) {
                monitorCount++;
            }else{
                eleCount++;
            }
        }
        map.put("towenCount",towenCount);
        map.put("liftCount",liftCount);
        map.put("hookCount",hookCount);
        map.put("alCount",alCount);
        map.put("monitorCount",monitorCount);
        map.put("eleCount",eleCount);
        return map;
    }
}
